home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / BCCAPP.ARJ / WINDOWS.C < prev    next >
C/C++ Source or Header  |  1991-09-15  |  9KB  |  463 lines

  1. /*
  2.  *
  3.  * Windows source implementation
  4.  *
  5.  * (C) 1990 Vision Software
  6.  *
  7.  * $Id: windows.c 1.2001 91/04/25 15:07:55 pcalvin release $
  8.  *
  9.  * Comments:
  10.  *
  11.  * Used by nearly every class that performs any screen I/O.  These interfaces
  12.  * will (hopefully) aid in porting any application under this system.
  13.  *
  14.  * Bugs:
  15.  *
  16.  * Not fully implemented.  Right now there is no window information storage
  17.  * for re-drawing a window moved to the top.
  18.  *
  19.  * No clipping of output should the window be written to when not on top..
  20.  *
  21.  * Some torture testing should be done to determine how stable this system
  22.  * is.  If we crash here, there isn't much hope for the rest of the library
  23.  *
  24.  * CODE DOCUMENTATION!!!!!!
  25.  *
  26.  */
  27. #include <string.h>
  28. #include <dos.h>
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <conio.h>
  32. #include <math.h>
  33. #include <ctype.h>
  34.  
  35. #include <stdhdr.h>
  36. #include <adl.h>
  37.  
  38. #include "lowlevel.h"
  39.  
  40. /*
  41.  * Windows may be constructed without arguements, in that case,
  42.  * they default to the entire screen with no border.
  43.  */
  44. WINDOW::WINDOW(ROW r1,COL c1,ROW r2,COL c2,CO coFore,CO coBack,SZ sz,BOOL fScroll)
  45.     {
  46.     rowTop = r1;
  47.     colLeft = c1;
  48.     rowBottom = r2;
  49.     colRight = c2;
  50.     coForeground = coFore;
  51.     coBackground = coBack;
  52.     fOpen = fFalse;
  53.     szTitle = sz;
  54.     fAutomaticScroll = fScroll;
  55.  
  56.     /*
  57.      *    Assert the window will fit, attempts to move it if the window doesn't fit.
  58.      */
  59.     VerifySz(FValidWindow(),"Window to large to fit on screen");
  60.     SetScrollRow(rowTop,rowBottom);
  61.     SetScrollCol(colLeft,colRight);
  62.     }
  63.  
  64. WINDOW::WINDOW(VOID)
  65.     {
  66.     rowTop = 2;
  67.     colLeft = 5;
  68.     rowBottom = 22;
  69.     colRight = 75;
  70.     coForeground = coBlack;
  71.     coBackground = coCyan;
  72.     fOpen = fFalse;
  73.     szTitle = szNil;
  74.     fAutomaticScroll = fFalse;
  75.     
  76.     SetScrollRow(rowTop,rowBottom);
  77.     SetScrollCol(colLeft,colRight);
  78.     }
  79.  
  80. WINDOW::~WINDOW()
  81.     {
  82.     if (fOpen)
  83.         Close();
  84.     }
  85.  
  86. ROW WINDOW::RowQuery()
  87.     {
  88.     return (rowTop);
  89.     }
  90.  
  91. COL WINDOW::ColQuery()
  92.     {
  93.     return (colLeft);
  94.     }
  95.  
  96. VOID WINDOW::Open(VOID)
  97.     {
  98.     if (!fOpen)
  99.         {
  100.         /*
  101.          * Save screen below window.
  102.          * puchBuffer == Original screen contents
  103.          */
  104.         puchBuffer = new UCHAR[(6+rowBottom-rowTop) * (6+colRight-colLeft) * 2];
  105.         MemoryAssert(puchBuffer);
  106.  
  107.         Save(puchBuffer);
  108.         fOpen = fTrue;
  109.         }
  110.  
  111.     SetRowCol(0,0);
  112.     Draw();
  113.     }
  114.  
  115. VOID WINDOW::Draw(VOID)
  116.     {
  117.     if (fOpen)
  118.         {
  119.         ClearWindow(rowTop,colLeft,rowBottom,colRight,coForeground,coBackground);
  120.         DrawBorder(rowTop-1,colLeft-1,rowBottom+1,colRight+1,bdDouble,coForeground,coBackground);
  121.  
  122.         if (szTitle != szNil)
  123.             DisplayCenter(rowTop-1,(colRight+colLeft)/2,szTitle,coForeground,coBackground);
  124.         }
  125.     }
  126.  
  127. VOID WINDOW::Close(VOID)
  128.     {
  129.     if (fOpen)
  130.         {
  131.         Restore(puchBuffer);
  132.         delete puchBuffer;
  133.         fOpen = fFalse;
  134.         }
  135.     }
  136.  
  137. VOID WINDOW::Restore(PUCH puch)
  138.     {
  139.     Assert(puch != puchNil);
  140.  
  141.     puttext(colLeft-1,rowTop-1,colRight+2,rowBottom+2,puch);
  142.     }
  143.  
  144. VOID WINDOW::Save(PUCH puch)
  145.     {
  146.     Assert(puch != puchNil);
  147.  
  148.     gettext(colLeft-1,rowTop-1,colRight+2,rowBottom+2,puch);
  149.     }
  150.  
  151. VOID WINDOW::Move(ROW row,COL col)
  152.     {
  153.     ROW drow = rowBottom-rowTop;
  154.     COL dcol = colRight-colLeft;
  155.  
  156.     Restore(puchBuffer);
  157.     rowTop = row;
  158.     colLeft = col;
  159.     rowBottom = row+drow;
  160.     colRight = col+dcol;
  161.     Save(puchBuffer);
  162.     Draw();
  163.     }
  164.  
  165. /*
  166.  * Updates the internal record of cursor position and sets position on
  167.  * the viewscreen..
  168.  */
  169. VOID WINDOW::SetRowCol(ROW row,COL col)
  170.     {
  171.     if (fOpen)
  172.         {
  173.         /*
  174.          * Before setting cursor, assert cursor is within screen.
  175.          */
  176.         if (rowTop + row > rowBottom)
  177.             row = rowBottom;
  178.  
  179.         if (colLeft + col > colRight)
  180.             col = colRight;
  181.             
  182.         /*
  183.          *    Now, set internal/external cursor
  184.          */
  185.         rowCurrent = row;
  186.         colCurrent = col;
  187.         SetGlobalRowCol(RowAbs(row),ColAbs(col));
  188.         }
  189.     }
  190.  
  191. /*
  192.  * Clears the entire window..
  193.  */
  194. VOID WINDOW::Cls(VOID)
  195.     {
  196.     if (fOpen)
  197.         {
  198.         ClearWindow(rowTop,colLeft,rowBottom,colRight,coForeground,coBackground);
  199.         SetRowCol(0,0);
  200.         }
  201.     }
  202.  
  203. /*
  204.  * Clear a specific row, does not adjust cursor..
  205.  */
  206. VOID WINDOW::ClearRow(ROW rowClear)
  207.     {
  208.     if (fOpen)
  209.         {
  210.         ROW row = RowAbs(rowClear);
  211.  
  212.         ClearWindow(row,colLeft,row,colRight,coForeground,coBackground);
  213.         }
  214.     }
  215.  
  216. /*
  217.  * Clear a specific column, also does not touch the cursor..
  218.  */
  219. VOID WINDOW::ClearCol(COL colClear)
  220.     {
  221.     if (fOpen)
  222.         {
  223.         COL col = ColAbs(colClear);
  224.  
  225.         ClearWindow(rowTop,col,rowBottom,col,coForeground,coBackground);
  226.         }
  227.     }
  228.  
  229. /*
  230.  * String output routines..
  231.  */
  232. VOID WINDOW::Say(SZ sz,CO coFore,CO coBack)
  233.     {
  234.     Assert(sz != szNil);
  235.  
  236.     /*
  237.      * Set up color if default arguments are used..
  238.      */
  239.     coFore = CoFromCoCo(coFore,coForeground);
  240.     coBack = CoFromCoCo(coBack,coBackground);
  241.  
  242.     if (fOpen)
  243.         {
  244.         REGISTER CHAR ch;
  245.         
  246.         /*
  247.          * Draw, keep text from going outside window
  248.          */
  249.         SetRowCol(rowCurrent,colCurrent);
  250.         CursorColor(coFore,coBack);
  251.         
  252.         while ((ch = *sz++) != chNil)
  253.             {
  254.             if (ch == chReturn)
  255.                 AdvanceRow();
  256.             else if (isprint(ch))
  257.                 putch(ch);
  258.  
  259.             AdvanceCol();
  260.             }
  261.         }
  262.     }
  263.  
  264. /*
  265.  * Sets new cursor position..
  266.  */
  267. VOID WINDOW::SayAt(ROW row,COL col,SZ sz,CO coFore,CO coBack)
  268.     {
  269.     SetRowCol(row,col);
  270.     Say(sz,coFore,coBack);
  271.     }
  272.  
  273. /*
  274.  * Displays a "Hot" string.  The CCH'th letter is highlighted
  275.  */
  276. VOID WINDOW::SayHot(ROW row,COL col,SZ sz,CCH cch,CO coFore,CO coBack)
  277.     {
  278.     ROW rowDisplay = RowAbs(row);
  279.     COL colDisplay = ColAbs(col);
  280.  
  281.     /*
  282.      * Normalize colours..
  283.      */
  284.     coFore = CoFromCoCo(coFore,coForeground);
  285.     coBack = CoFromCoCo(coBack,coBackground);
  286.  
  287.     HotString(rowDisplay,colDisplay,cch,sz,coFore,coBack);
  288.     }
  289.  
  290. /*
  291.  * Centers the text on the desired row
  292.  */
  293. VOID WINDOW::SayCentered(ROW row,SZ sz,CO coFore,CO coBack)
  294.     {
  295.     ROW rowDisplay = RowAbs(row);
  296.     COL colDisplay = ColAbs((colRight-colLeft) >> 1);
  297.  
  298.     /*
  299.      * Normalize colours..
  300.      */
  301.     coFore = CoFromCoCo(coFore,coForeground);
  302.     coBack = CoFromCoCo(coBack,coBackground);
  303.  
  304.     DisplayCenter(rowDisplay,colDisplay,sz,coFore,coBack);
  305.     }
  306.  
  307. /*
  308.  * Outputs a single character at the current location..
  309.  */
  310. VOID WINDOW::PutCh(CHAR ch,CO coFore,CO coBack)
  311.     {
  312.     /*
  313.      * Normalize colours..
  314.      */
  315.     coFore = CoFromCoCo(coFore,coForeground);
  316.     coBack = CoFromCoCo(coBack,coBackground);
  317.  
  318.     if (fOpen)
  319.         {
  320.         SetRowCol(rowCurrent,colCurrent);
  321.         CursorColor(coFore,coBack);
  322.         if (isprint(ch))
  323.             {
  324.             putch(ch);
  325.             AdvanceCol();
  326.             }
  327.         else if (ch == chReturn)
  328.             {
  329.             AdvanceRow();
  330.             }
  331.         }
  332.     }
  333.  
  334. /*
  335.  *
  336.  * Windows internal operation
  337.  *
  338.  */
  339.  
  340. /*
  341.  * Advances the cursor position..
  342.  */
  343. VOID WINDOW::AdvanceCol()
  344.     {
  345.     COL colLast = colRight - colLeft;
  346.  
  347.     if (++colCurrent > colLast)
  348.         {
  349.         colCurrent = 0;
  350.         AdvanceRow();
  351.         }
  352.  
  353.     SetRowCol(rowCurrent,colCurrent);
  354.     }
  355.  
  356. VOID WINDOW::AdvanceRow()
  357.     {
  358.     ROW rowLast = rowBottom - rowTop;
  359.  
  360.     /*
  361.      * Be sure to before a return with the linefeed.
  362.      */
  363.     colCurrent = 0;
  364.     
  365.     /*
  366.      * The window is only scrolled up if automatic cursor
  367.      *    addressing is to be observed.
  368.      */
  369.     if (++rowCurrent > rowLast)
  370.         {
  371.         rowCurrent--;
  372.         if (fAutomaticScroll)
  373.             ScrollDrow(1);
  374.         }
  375.  
  376.     SetRowCol(rowCurrent,colCurrent);
  377.     }
  378.  
  379. /*
  380.  * Allows normalizing of the colors.  coDefault is used if co==coError
  381.  */
  382. CO WINDOW::CoFromCoCo(CO co,CO coDefault)
  383.     {
  384.     return ((co == coError) ? coDefault : co);
  385.     }
  386.  
  387. /*
  388.  *    Functions to answer with the ABSOLUTE screen position.  Will keep
  389.  *    cursor within the window
  390.  */
  391. ROW WINDOW::RowAbs(ROW row)
  392.     {
  393.     ROW rowAbs = rowTop + row;
  394.  
  395.     return ((rowAbs < rowBottom) ? rowAbs : rowBottom);
  396.     }
  397.  
  398. ROW WINDOW::ColAbs(COL col)
  399.     {
  400.     COL colAbs = colLeft + col;
  401.     
  402.     return ((colAbs < colRight) ? colAbs : colRight);
  403.     }
  404.  
  405. VOID WINDOW::SetScrollRow(ROW rowFirst,ROW rowLast)
  406.     {
  407.     rowScrollTop = (rowFirst >= rowTop) ? rowFirst : rowTop;
  408.     rowScrollBottom = (rowLast <= rowBottom) ? rowLast : rowBottom;
  409.     }
  410.  
  411. VOID WINDOW::SetScrollCol(COL colFirst,COL colLast)
  412.     {
  413.     colScrollLeft = (colFirst >= colLeft) ? colFirst : colLeft;
  414.     colScrollRight = (colLast <= colRight) ? colLast : colRight;
  415.     }
  416.     
  417. VOID WINDOW::ScrollDrow(ROW drow)
  418.     {
  419.     if (drow > 0)
  420.         {
  421.         movetext(colScrollLeft,rowScrollTop+drow,colScrollRight,rowScrollBottom,colScrollLeft,rowScrollTop);
  422.         ClearRow(rowScrollBottom-rowTop);
  423.         }
  424.     else if (drow < 0)
  425.         {
  426.         movetext(colScrollLeft,rowScrollTop,colScrollRight,rowScrollBottom+drow,colScrollLeft,rowScrollTop-drow);
  427.         ClearRow(0);
  428.         }
  429.     }
  430.  
  431. /*
  432.  *    Asserts that window is small enough to fit on the screen.  Also makes sure
  433.  *    the window does not travel off the screen.
  434.  *    Must leave 2 columns at right edge for border + shadow
  435.  *    Also, must leave 3 rows at bottom for border/shadow and help
  436.  */
  437. BOOL WINDOW::FValidWindow()
  438.     {
  439.     /*
  440.      *    First, assert the horizontal measurements..
  441.      */
  442.     if (colRight+2 >= colGlobalWindowRight)
  443.         {
  444.         COL dcol = 2 + colRight - colGlobalWindowRight;
  445.  
  446.         colRight -= dcol;
  447.         colLeft -= dcol;
  448.         }
  449.     
  450.     /*
  451.      *    Now the vertical measurements..
  452.      */
  453.     if (rowBottom+3 >= rowGlobalWindowBottom)
  454.         {
  455.         ROW drow = 3 + rowBottom - rowGlobalWindowBottom;
  456.  
  457.         rowBottom -= drow;
  458.         rowTop -= drow;
  459.         }
  460.     
  461.     return (fTrue);
  462.     }
  463.